package com.ww.springboot.boot.controller;

import com.ww.springboot.boot.config.RedisUtils;
import com.ww.springboot.boot.service.IRedisService;
import com.ww.springboot.boot.service.impl.RedisServiceImpl;
import lombok.AllArgsConstructor;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;


/**
 * @author ZH500
 */
@RestController
@RequestMapping("redis")
@AllArgsConstructor
public class RedisPlusController {

    private final IRedisService redisService;

    private final RedisUtils redisUtils;

    private final StringRedisTemplate redisTemplate;

//    private final RedissonClient redissonClient;

    /**
     * 秒杀
     * <p>
     * 1.使用多线程模拟高并发
     * <p>
     * 2.使用redis + mysql 模拟 redis击穿 穿透等场景
     * <p>
     * 3.使用redis分布式锁 解决问题
     * <p>
     * 4.自己实现简单的分布式锁
     *
     * @return
     */
    @RequestMapping("/secKill")
    public String secKill() throws InterruptedException {
        ExecutorService executorService = new ThreadPoolExecutor(1000, 1000,
                1, TimeUnit.SECONDS, new LinkedBlockingDeque<>(2000), new CustomizableThreadFactory("secKill_test-thread-pool"));
        for (int n = 0; n < 1000; n++) {
            //1000线程池
            executorService.execute(() -> {
                //100线程
                IntStream.range(0, 100).parallel().forEach((i) -> redisService.secKill(String.valueOf(Integer.valueOf((int) (Math.random() * 11)) % 11)));
            });
        }
        executorService.shutdown();
        while (!executorService.awaitTermination(10, TimeUnit.MILLISECONDS)) {

        }
        return "success";
    }

    /**
     * 秒杀
     * <p>
     * 1.使用多线程模拟高并发
     * <p>
     * 2.使用redis + mysql 模拟 redis击穿 穿透等场景
     * <p>
     * 3.使用redis分布式锁 解决问题
     * <p>
     * 4.自己实现简单的分布式锁
     *
     * @return
     */
    @RequestMapping("/secKillTest")
    public String secKillTest() throws InterruptedException {
        ExecutorService executorService = new ThreadPoolExecutor(1000, 1000,
                1, TimeUnit.SECONDS, new LinkedBlockingDeque<>(2000), new CustomizableThreadFactory("secKill_test-thread-pool"));
        for (int n = 0; n < 1000; n++) {
            executorService.execute(() -> {
                int i = 0;
                while (i < 100) {
                    i++;
                    redisUtils.get(RedisServiceImpl.secKill + String.valueOf(Integer.valueOf((int) (Math.random() * 11)) % 11));
                }
            });
        }
        executorService.shutdown();
        while (!executorService.awaitTermination(10, TimeUnit.MILLISECONDS)) {

        }
        return "success";
    }

    /**
     * 秒杀
     * <p>
     * 1.使用多线程模拟高并发
     * <p>
     * 2.使用redis + mysql 模拟 redis击穿 穿透等场景
     * <p>
     * 3.使用redis分布式锁 解决问题
     * <p>
     * 4.自己实现简单的分布式锁
     *
     * @return
     */
    @RequestMapping("/secKillTest2")
    public String secKillTest2() throws InterruptedException {
        ExecutorService executorService = new ThreadPoolExecutor(1000, 1000,
                1, TimeUnit.SECONDS, new LinkedBlockingDeque<>(2000), new CustomizableThreadFactory("secKill_test-thread-pool"));

        for (int n = 0; n < 1000; n++) {
            executorService.execute(() -> {
                int i = 0;
                while (i < 100) {
                    i++;
                    //redisUtils.get(RedisServiceImpl.secKill + i);
                }
            });
        }
        executorService.shutdown();
        while (!executorService.awaitTermination(10, TimeUnit.MILLISECONDS)) {

        }
        return "success";
    }

    @RequestMapping("/redisTest")
    public String redisTest() throws InterruptedException {
        Date date = new Date();
        Instant instant = date.toInstant();
        date = Date.from(instant.plus(Duration.ofSeconds(-50)));
        for (int i = 0; i < 1010; i++) {
            Thread.sleep(10);
            redisTemplate.opsForHash().increment("incr:test", "test", 1);
            System.out.println((String) redisTemplate.opsForHash().get("incr:test", "test"));
            redisTemplate.expireAt("incr:test", date);
            System.out.println((String) redisTemplate.opsForHash().get("incr:test", "test"));
        }
        return "";
    }

    @RequestMapping("/redisTest2")
    public String redisTest2() throws InterruptedException {

        for (int i = 0; i < 10000; i++) {
            Thread.sleep(10);
            Date date = new Date();
            Instant instant = date.toInstant();
            date = Date.from(instant.plus(Duration.ofSeconds(-55)));
            redisTemplate.expireAt("incr:test", date);
            Thread.sleep(1000);
            redisTemplate.opsForHash().increment("incr:test", "test", 1);
            System.out.println((String) redisTemplate.opsForHash().get("incr:test", "test"));
        }
        return "";
    }

//    @RequestMapping("bloomFilter")
//    public String bloomFilter(String key, String value) {
//        RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter("phoneList");
//        //初始化布隆过滤器：预计元素为100000000L,误差率为3%
//        bloomFilter.tryInit(100000000L, 0.03);
//        //将号码10086插入到布隆过滤器中
//        bloomFilter.add("10086");
//        //判断下面号码是否在布隆过滤器中
//        System.out.println(bloomFilter.contains("123456"));//false
//        System.out.println(bloomFilter.contains("10086"));//true
//        return "";
//    }
}
